package com.example.annotatedclass;

import cn.hutool.core.util.ObjectUtil;
import com.example.annotations.ConvertTargetClass;
import com.example.annotations.ConvertTargetField;
import com.example.exception.ProcessingException;
import com.sun.tools.javac.code.Symbol;


import javax.lang.model.element.Element;
import javax.lang.model.element.NestingKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.MirroredTypeException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ClassAnnotatedBean {

    /**
     * annotated class name
     */
    private TypeElement annotatedClassElement;
    /**
     * super class name
     */
    private String qualifiedSuperClassName;
    /**
     * simple name
     */
    private String simpleTypeName;
    /**
     * ConvertTargetField value()
     */
    private String value;
    /**
     * class field bean
     */
    private List<FieldAnnotatedBean> fieldMap = new ArrayList<>();


    public ClassAnnotatedBean(TypeElement classElement) throws IllegalArgumentException {
        this.annotatedClassElement = classElement;
        ConvertTargetClass classAnnot = classElement.getAnnotation(ConvertTargetClass.class);

        // Get the full QualifiedTypeName
        try {
            Class<?> clazz = classAnnot.value();
            qualifiedSuperClassName = clazz.getCanonicalName();
            simpleTypeName = clazz.getSimpleName();
        } catch (MirroredTypeException mte) {
            DeclaredType classTypeMirror = (DeclaredType) mte.getTypeMirror();
            TypeElement classTypeElement = (TypeElement) classTypeMirror.asElement();
            qualifiedSuperClassName = classTypeElement.getQualifiedName().toString();
            simpleTypeName = classTypeElement.getSimpleName().toString();
        }

        for (Element e : classElement.getEnclosedElements()){ // iterate over children
            try{
                addSubClassFields(e);
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }

    }


    /**
     * 递归去查找路径下的类 的字段,将注解字段加入集合中
     * @param field
     * @return
     */
    public void addSubClassFields(Element field) throws IllegalArgumentException {
        if(field.getKind().isField()){
            ConvertTargetField fieldAnnot = field.getAnnotation(ConvertTargetField.class);
            ConvertTargetClass classAnnot = field.getAnnotation(ConvertTargetClass .class);
            if(ObjectUtil.isNotEmpty(classAnnot)){
                (((Symbol)field).type).tsym.members().getElements().forEach(x -> {
                    addSubClassFields(x);
                });
            }
            if(ObjectUtil.isNotEmpty(fieldAnnot)){//字段
                fieldMap.add(new FieldAnnotatedBean(field));
            }

        }

    }

    /**
     * 获取在{@link ConvertTargetClass#value()}中指定的id
     * return the id
     */
    public String getValue() {
        return value;
    }

    /**
     * 获取在{@link ConvertTargetClass#value()}指定的类型合法全名
     *
     * @return qualified name
     */
    public String getQualifiedFactoryGroupName() {
        return qualifiedSuperClassName;
    }


    /**
     * 获取在 {@link ConvertTargetClass#value()} 中指定的类型的简单名字
     *
     * @return qualified name
     */
    public String getSimpleFactoryGroupName() {
        return simpleTypeName;
    }

    /**
     * 获取被@Factory注解的原始元素
     */
    public TypeElement getTypeElement() {
        return annotatedClassElement;
    }

    public List<FieldAnnotatedBean> getFieldMap() {
        return fieldMap;
    }

    public void setFieldMap(List<FieldAnnotatedBean> fieldMap) {
        this.fieldMap = fieldMap;
    }
}
